﻿//
// Created by Grishul Eugeny
//
// See license in License.txt
//

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Reflection;
using NCommander.NodeProviders;
using NCommander.Core;

namespace NCommander
{
	public partial class NodeView : UserControl, IViewProvider
	{
		private NodeProvider _nodeProvider;
		
		public NodeView()
		{
			InitializeComponent();

			_recentDirectories.DataSource = _navigationHistory;
		}


		#region Navigation history

		private sealed class NavigationEntry
		{
			public Type FileProvider;
			public string FullPath;

			public override string ToString()
			{
				return FullPath;
			}
		}

		private readonly List<NavigationEntry> _navigationHistory = new List<NavigationEntry>();
		protected void DirectoryNavigated()
		{
			var index = _navigationHistory.FindIndex( x => x.FileProvider == NodeProvider.GetType() && x.FullPath == NodeProvider.CurrentNode.Path );

			if( index != -1 )
			{
				var element = _navigationHistory[index];
				_navigationHistory.RemoveAt( index );

				_navigationHistory.Insert( 0, element );
			}
			else
			{
				var entry = new NavigationEntry { FileProvider = NodeProvider.GetType(), FullPath = NodeProvider.CurrentNode.Path };
				_navigationHistory.Insert( 0, entry );
			}

			_recentDirectories.DataSource = null;
			_recentDirectories.DataSource = _navigationHistory;
		}

		#endregion

		public override void Refresh()
		{
			OnProviderRefresh( NodeProvider, EventArgs.Empty );
			base.Refresh();
		}

		public virtual void OnProviderRefresh( object provider, EventArgs args )
		{
		}

		private void _recentDirectories_Validated( object sender, EventArgs e )
		{
			var lastDirectory = NodeProvider.CurrentNode;

			try
			{
				NodeProvider.CurrentNode = NodeProvider.GetNode( _recentDirectories.Text );
				Refresh();
			}
			catch
			{
				NodeProvider.CurrentNode = lastDirectory;
				Refresh();
			}
		}

		private void _type_MouseClick( object sender, MouseEventArgs e )
		{
			if( e.Button != MouseButtons.Right )
				return;

			var menu = new ContextMenuStrip();
			foreach( var provider in Assembly.GetExecutingAssembly().GetTypes().Where( x => x.IsSubclassOf( typeof( NodeProvider ) ) ) )
			{
				var item = menu.Items.Add( provider.GetAttribute<ShortNameAttribute>().Value );
				item.Tag = provider;

				item.Click += ( x, y ) =>
				{
					NodeProvider = ( NodeProvider ) Activator.CreateInstance( ( x as ToolStripItem ).Tag as Type );
					Refresh();
				};
			}

			menu.Show( _type, e.X, e.Y );
		}

		private void _roots_DropDown( object sender, EventArgs e )
		{
			_roots.DataSource = NodeProvider.Roots;
		}

		private void _roots_SelectedIndexChanged( object sender, EventArgs e )
		{
			NodeProvider.CurrentNode = ( Node ) _roots.SelectedItem;
		}

		private void _files_DoubleClick( object sender, EventArgs e )
		{
			NodeProvider.OnExecute( SelectedNodes[0] );
		}

		#region IViewProvider Members

		public Node[] SelectedNodes
		{
			get
			{
				return _nodes.SelectedItems.Cast<ListViewItem>().Select( x => x.Tag as Node ).ToArray();
			}
			set
			{
				throw new NotImplementedException();
			}
		}

		public NodeProvider NodeProvider
		{
			get { return _nodeProvider; }
			set
			{
				if( _nodeProvider != null )
					_nodeProvider.Refresh -= OnProviderRefresh;

				_nodeProvider = value;

				if( _nodeProvider != null )
				{
					_nodeProvider.Refresh += OnProviderRefresh;
					_type.Text = NodeProvider.GetType().GetAttribute<ShortNameAttribute>().Value;
				}
			}
		}

		public void SelectAll()
		{
			foreach( ListViewItem item in _nodes.Items )
				item.Selected = true;
		}

		public string TabCaption
		{
			get { return Path.GetFileName( _nodeProvider.CurrentNode.Path ); }
		}

		public event EventHandler TabCaptionChanged;

		#endregion
	}
}
